import requests
import json
import time
from typing import List, Dict, Any, Optional
from urllib.parse import quote

# 添加项目根目录到Python路径
import sys
import os
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if project_root not in sys.path:
    sys.path.append(project_root)

from processors.platform_apis import get_endpoint_url, get_platform_config


class GhostCutVideoTranslator:
    """
    GhostCut 视频翻译音频处理工具类
    用于调用鬼手剪辑的视频翻译和配音API
    """

    def __init__(self, app_key: str, app_secret: str):
        """
        初始化GhostCut视频翻译工具
        
        Args:
            app_key (str): GhostCut平台的AppKey
            app_secret (str): GhostCut平台的AppSecret
        """
        self.app_key = app_key
        self.app_secret = app_secret
        
        # 获取平台配置
        self.platform_config = get_platform_config("ghostcut")
        
        # 获取基础URL和状态URL
        base_endpoint = get_endpoint_url("ghostcut", "video_translate")
        status_endpoint = get_endpoint_url("ghostcut", "video_status")
        retry_endpoint = get_endpoint_url("ghostcut", "video_retry")
        
        self.base_url = base_endpoint or "https://api.zhaoli.com/v-w-c/gateway/ve/work/free"
        self.status_url = status_endpoint or "https://api.zhaoli.com/v-w-c/gateway/ve/work/status"
        self.retry_url = retry_endpoint or "https://cn.jollytoday.com/v-w-c/ve/work/retry"

    def _generate_signature(self, body: str) -> str:
        """
        生成API签名
        
        Args:
            body (str): 请求体的JSON字符串
            
        Returns:
            str: 签名字符串
        """
        import hashlib
        md5_body = hashlib.md5(body.encode('utf-8')).hexdigest()
        sign_string = md5_body + self.app_secret
        signature = hashlib.md5(sign_string.encode('utf-8')).hexdigest()
        return signature

    def translate_videos(self, 
                        urls: List[str], 
                        source_lang: str, 
                        target_lang: str,
                        names: Optional[List[str]] = None,
                        resolution: str = "1080p",
                        callback: Optional[str] = None,
                        uid: Optional[str] = None,
                        wy_voice_param: Optional[Dict] = None,
                        remove_bg_audio: int = 0,
                        extra_options: Optional[Dict] = None) -> Dict[str, Any]:
        """
        调用视频翻译API处理视频
        
        Args:
            urls (List[str]): 需要处理的视频URL列表，最多不超过20个
            source_lang (str): 源语言代码 (如: zh)
            target_lang (str): 目标语言代码 (如: en)
            names (List[str], optional): 为传入的urls命名，与urls一一对应
            resolution (str): 分辨率，支持 480p、720p、1080p，默认1080p
            callback (str, optional): 回调地址URL
            uid (str, optional): 用户ID
            wy_voice_param (Dict, optional): 配音&字幕配置信息
            remove_bg_audio (int): 如何处理原视频的背景声 (0:保留背景音, 1:背景音静音, 2:保留效果音)
            extra_options (Dict, optional): 额外的剪辑配置
            
        Returns:
            dict: API响应结果
        """
        if len(urls) > 20:
            raise ValueError("一次最多处理20个视频URL")
        
        # 检查URL中是否包含中文字符
        for url in urls:
            if self._contains_chinese(url):
                raise ValueError(f"URL不能包含中文字符: {url}")
        
        # 构造基础参数
        payload = {
            "urls": urls,
            "sourceLang": source_lang,
            "lang": target_lang,
            "needWanyin": 1,
            "wyTaskType": "FULL",
            "wyNeedText": 1,
            "removeBgAudio": remove_bg_audio,
            "needChineseOcclude": 1
        }
        
        # 添加可选参数
        if names:
            payload["names"] = names
        if resolution:
            payload["resolution"] = resolution
        if callback:
            payload["callback"] = callback
        if uid:
            payload["uid"] = uid
        if wy_voice_param:
            payload["wyVoiceParam"] = json.dumps(wy_voice_param, ensure_ascii=False)
        if extra_options:
            payload["extraOptions"] = json.dumps(extra_options, ensure_ascii=False)
        
        # 发送请求
        return self._send_request(payload, self.base_url)

    def remove_text_and_translate(self,
                                 urls: List[str],
                                 source_lang: str,
                                 target_lang: str,
                                 names: Optional[List[str]] = None,
                                 resolution: str = "1080p",
                                 callback: Optional[str] = None,
                                 uid: Optional[str] = None,
                                 wy_voice_param: Optional[Dict] = None,
                                 extra_options: Optional[Dict] = None) -> Dict[str, Any]:
        """
        去除视频文字并进行翻译处理
        
        Args:
            urls (List[str]): 需要处理的视频URL列表，最多不超过20个
            source_lang (str): 源语言代码 (如: zh)
            target_lang (str): 目标语言代码 (如: en)
            names (List[str], optional): 为传入的urls命名，与urls一一对应
            resolution (str): 分辨率，支持 480p、720p、1080p，默认1080p
            callback (str, optional): 回调地址URL
            uid (str, optional): 用户ID
            wy_voice_param (Dict, optional): 配音&字幕配置信息
            extra_options (Dict, optional): 额外的剪辑配置
            
        Returns:
            dict: API响应结果
        """
        if len(urls) > 20:
            raise ValueError("一次最多处理20个视频URL")
        
        # 检查URL中是否包含中文字符
        for url in urls:
            if self._contains_chinese(url):
                raise ValueError(f"URL不能包含中文字符: {url}")
        
        # 构造基础参数
        payload = {
            "urls": urls,
            "sourceLang": source_lang,
            "lang": target_lang,
            "needWanyin": 1,
            "wyTaskType": "FULL",
            "wyNeedText": 1,
            "removeText": 1  # 去除视频文字
        }
        
        # 添加可选参数
        if names:
            payload["names"] = names
        if resolution:
            payload["resolution"] = resolution
        if callback:
            payload["callback"] = callback
        if uid:
            payload["uid"] = uid
        if wy_voice_param:
            payload["wyVoiceParam"] = json.dumps(wy_voice_param, ensure_ascii=False)
        if extra_options:
            payload["extraOptions"] = json.dumps(extra_options, ensure_ascii=False)
        
        # 发送请求
        return self._send_request(payload, self.base_url)

    def _contains_chinese(self, text: str) -> bool:
        """
        检查字符串是否包含中文字符
        
        Args:
            text (str): 要检查的字符串
            
        Returns:
            bool: 如果包含中文字符返回True，否则返回False
        """
        for ch in text:
            if '\u4e00' <= ch <= '\u9fff':
                return True
        return False

    def _send_request(self, payload: Dict[str, Any], url: str) -> Dict[str, Any]:
        """
        发送API请求
        
        Args:
            payload (dict): 请求参数
            url (str): 请求地址
            
        Returns:
            dict: API响应结果
        """
        # 转换为JSON字符串
        body = json.dumps(payload, ensure_ascii=False)
        
        # 生成签名
        signature = self._generate_signature(body)
        
        # 设置请求头
        headers = {
            "Content-Type": "application/json",
            "AppKey": self.app_key,
            "AppSign": signature
        }
        
        # 发送POST请求
        response = requests.post(url, data=body.encode('utf-8'), headers=headers)
        response.raise_for_status()
        
        return response.json()

    def query_task_status(self, id_works: Optional[List[int]] = None, 
                         id_projects: Optional[List[int]] = None,
                         page: Optional[int] = None,
                         page_size: Optional[int] = None,
                         create_time_greater_than_or_equal_to: Optional[int] = None,
                         create_time_less_than: Optional[int] = None) -> Dict[str, Any]:
        """
        查询任务处理状态
        
        Args:
            id_works (List[int], optional): 作品ID列表，优先级最高
            id_projects (List[int], optional): 任务ID列表
            page (int, optional): 页码, 从0开始，不需要分页传None
            page_size (int, optional): 查询条数, 不需要分页传None，最大2000
            create_time_greater_than_or_equal_to (int, optional): 查询创建时间大于或等于该值的数据(时间戳毫秒)
            create_time_less_than (int, optional): 查询创建时间小于该值的数据(时间戳毫秒)
            
        Returns:
            dict: 任务状态信息
        """
        # 构造请求参数
        payload = {}
        
        if id_works:
            payload["idWorks"] = id_works
        elif id_projects:
            payload["idProjects"] = id_projects
            
        if page is not None:
            payload["page"] = page
        if page_size is not None:
            payload["pageSize"] = page_size
        if create_time_greater_than_or_equal_to is not None:
            payload["createTimeGreaterThanOrEqualTo"] = create_time_greater_than_or_equal_to
        if create_time_less_than is not None:
            payload["createTimeLessThan"] = create_time_less_than
        
        # 发送请求
        return self._send_request(payload, self.status_url)

    def query_task_status_by_work_ids(self, work_ids: List[int]) -> Dict[str, Any]:
        """
        通过作品ID查询任务状态
        
        Args:
            work_ids (List[int]): 作品ID列表
            
        Returns:
            dict: 任务状态信息
        """
        return self.query_task_status(id_works=work_ids)

    def query_task_status_by_project_ids(self, project_ids: List[int]) -> Dict[str, Any]:
        """
        通过任务ID查询任务状态
        
        Args:
            project_ids (List[int]): 任务ID列表
            
        Returns:
            dict: 任务状态信息
        """
        return self.query_task_status(id_projects=project_ids)

    def wait_for_completion(self, work_ids: List[int], 
                           check_interval: int = 10, 
                           max_wait_time: int = 3600) -> Dict[str, Any]:
        """
        等待任务完成并返回结果
        
        Args:
            work_ids (List[int]): 作品ID列表
            check_interval (int): 检查间隔(秒)，默认10秒
            max_wait_time (int): 最大等待时间(秒)，默认3600秒(1小时)
            
        Returns:
            dict: 任务状态信息
        """
        start_time = time.time()
        while time.time() - start_time < max_wait_time:
            try:
                result = self.query_task_status_by_work_ids(work_ids)
                content = result.get("body", {}).get("content", [])
                
                # 检查所有任务是否完成
                all_completed = True
                for item in content:
                    status = item.get("processStatus", 0)
                    # 状态码 <1 表示处理中，1 表示成功，>1 表示失败
                    if status < 1:
                        all_completed = False
                        break
                
                if all_completed:
                    return result
                    
                # 等待下次检查
                time.sleep(check_interval)
            except Exception as e:
                print(f"查询任务状态时出错: {e}")
                time.sleep(check_interval)
        
        # 超时返回最后查询的结果
        return self.query_task_status_by_work_ids(work_ids)

    def retry_task(self, task_id: int) -> Dict[str, Any]:
        """
        重试失败的任务
        
        Args:
            task_id (int): 任务ID
            
        Returns:
            dict: API响应结果
        """
        # 构造请求参数
        payload = {
            "id": task_id,
            "zl_ts": int(time.time() * 1000),  # 毫秒时间戳
            "zl_zone": 8  # 时区，默认为8
        }
        
        # 发送请求，使用在__init__中初始化的self.retry_url
        return self._send_request(payload, self.retry_url)
